import { Box, Card, Page, Text } from '@shopify/polaris'
import type { LoaderFunction, ActionFunction } from '@remix-run/node'
import { json } from '@remix-run/node'
import { useLoaderData, useFetcher } from '@remix-run/react'
import { useEffect } from 'react'

// 生成 1 到 6 之间的随机数
async function rollDice() {
  return new Promise<number>((resolve) => {
    setTimeout(() => {
      resolve(Math.floor(Math.random() * 6) + 1)
    }, 3000)
  })
}

// loader 函数，服务端执行，一般用于获取初始数据并传递给对应的组件。
// 这里是调用rollDice方法生成随机数，传递给Dice组件。默认情况下，Dice组件会等待 loader 函数执行完毕后再渲染。
export const loader: LoaderFunction = async () => {
  console.log('加载Loader', new Date().toTimeString().split(' ')[0])
  const initialRoll = await rollDice() // 生成初始随机数
  console.log('Loader结果', initialRoll, new Date().toTimeString().split(' ')[0]) // 输出首次摇到的数字
  return json({ roll: initialRoll })
}

// shouldRevalidate函数：用于控制在调用 action 时是否重新执行 loader。
// 这里返回 false，表示调用 action 时不需要重新执行 loader 函数。Remix
export function shouldRevalidate() {
  return false
}

// action 函数，服务端执行，一般用于处理非Get请求（这里是重新摇骰子的请求）。
// 这个例子中，下方组件中定义了一个Form表单，表单没有指定action即默认执行当前的action函数
export const action: ActionFunction = async () => {
  const newRoll = await rollDice() // 生成新的随机数
  console.log('重摇', newRoll) // 输出重摇到的数字
  return json({ roll: newRoll }) // 返回包含新摇到数字的 JSON 数据
}

// 用于展示摇骰子页面的组件，客户端执行
export default function Dice() {
  // 在组件挂载时，useLoaderData 钩子会从服务器获取由 loader 函数提供的数据（初始的骰子大小）。组件可以使用获取到的数据进行渲染。
  const { roll } = useLoaderData<{ roll: number }>()
  // useFetcher 用于处理表单提交等操作。在这个例子中，当用户点击 "重摇" 按钮提交表单时，会触发 fetcher 的提交状态变化。
  const fetcher = useFetcher<{ roll: number }>()
  // 通过判断 fetcher.state 的值，可以确定当前是否正在提交（isRolling），以及获取最新的数据（fetcher.data?.roll）用于组件的渲染。
  const isRolling = fetcher.state === 'submitting' // 判断是否正在摇
  const currentRoll = fetcher.data?.roll ?? roll // 获取当前摇到的数字
  useEffect(() => {
    console.log('组件渲染', currentRoll, new Date().toTimeString().split(' ')[0])
  }, [currentRoll])
  return (
    <Page>
      <Box>
        <Card>
          <Text as="h1" variant="headingMd">
            摇骰子
          </Text>
          <p>当前点数: {isRolling ? '摇动中...' : currentRoll}</p>
          <fetcher.Form method="post">
            <button type="submit" disabled={isRolling}>
              {isRolling ? '摇动中...' : '重摇'}
            </button>
          </fetcher.Form>
        </Card>
      </Box>
    </Page>
  )
}
